{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:54:08.808942Z",
     "start_time": "2025-02-26T15:54:08.799746Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "\n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.6.0+cu118\n",
      "cuda:0\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 准备数据"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.426150Z",
     "start_time": "2025-02-26T15:30:50.086025Z"
    }
   },
   "source": [
    "from tensorflow import keras  #这里的波浪线不用管\n",
    "\n",
    "#用karas有的数据集imdb，电影分类,分电影是积极的，还是消极的\n",
    "#imdb是个对象，有各种接口\n",
    "imdb = keras.datasets.imdb\n",
    "#载入数据使用下面两个参数\n",
    "#只有数据集中出现频率最高的前 10,000 个单词会被保留，其余的单词会被替换为特殊索引（通常是 2，表示未知单词）。\n",
    "vocab_size = 10000  \n",
    "index_from = 3  #0,1,2,3空出来做别的事\n",
    "#前一万个词出现词频最高的会保留下来进行处理，后面的作为特殊字符处理，\n",
    "# 小于3的id都是特殊字符，下面代码有写\n",
    "# 需要注意的一点是取出来的词表还是从1开始的，需要做处理\n",
    "#使用index_from=3，表示索引从4开始，0,1,2,3空出来做别的事\n",
    "(train_data, train_labels), (test_data, test_labels) = imdb.load_data(\n",
    "    num_words=vocab_size, index_from=index_from)"
   ],
   "outputs": [],
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "source": [
    "type(train_labels)"
   ],
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "source": [
    "print(type(train_data))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.471498Z",
     "start_time": "2025-02-26T15:31:01.441994Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "cell_type": "code",
   "source": [
    "type(train_data[0])\n",
    "train_data[2]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.483457Z",
     "start_time": "2025-02-26T15:31:01.475967Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,\n",
       " 14,\n",
       " 47,\n",
       " 8,\n",
       " 30,\n",
       " 31,\n",
       " 7,\n",
       " 4,\n",
       " 249,\n",
       " 108,\n",
       " 7,\n",
       " 4,\n",
       " 5974,\n",
       " 54,\n",
       " 61,\n",
       " 369,\n",
       " 13,\n",
       " 71,\n",
       " 149,\n",
       " 14,\n",
       " 22,\n",
       " 112,\n",
       " 4,\n",
       " 2401,\n",
       " 311,\n",
       " 12,\n",
       " 16,\n",
       " 3711,\n",
       " 33,\n",
       " 75,\n",
       " 43,\n",
       " 1829,\n",
       " 296,\n",
       " 4,\n",
       " 86,\n",
       " 320,\n",
       " 35,\n",
       " 534,\n",
       " 19,\n",
       " 263,\n",
       " 4821,\n",
       " 1301,\n",
       " 4,\n",
       " 1873,\n",
       " 33,\n",
       " 89,\n",
       " 78,\n",
       " 12,\n",
       " 66,\n",
       " 16,\n",
       " 4,\n",
       " 360,\n",
       " 7,\n",
       " 4,\n",
       " 58,\n",
       " 316,\n",
       " 334,\n",
       " 11,\n",
       " 4,\n",
       " 1716,\n",
       " 43,\n",
       " 645,\n",
       " 662,\n",
       " 8,\n",
       " 257,\n",
       " 85,\n",
       " 1200,\n",
       " 42,\n",
       " 1228,\n",
       " 2578,\n",
       " 83,\n",
       " 68,\n",
       " 3912,\n",
       " 15,\n",
       " 36,\n",
       " 165,\n",
       " 1539,\n",
       " 278,\n",
       " 36,\n",
       " 69,\n",
       " 2,\n",
       " 780,\n",
       " 8,\n",
       " 106,\n",
       " 14,\n",
       " 6905,\n",
       " 1338,\n",
       " 18,\n",
       " 6,\n",
       " 22,\n",
       " 12,\n",
       " 215,\n",
       " 28,\n",
       " 610,\n",
       " 40,\n",
       " 6,\n",
       " 87,\n",
       " 326,\n",
       " 23,\n",
       " 2300,\n",
       " 21,\n",
       " 23,\n",
       " 22,\n",
       " 12,\n",
       " 272,\n",
       " 40,\n",
       " 57,\n",
       " 31,\n",
       " 11,\n",
       " 4,\n",
       " 22,\n",
       " 47,\n",
       " 6,\n",
       " 2307,\n",
       " 51,\n",
       " 9,\n",
       " 170,\n",
       " 23,\n",
       " 595,\n",
       " 116,\n",
       " 595,\n",
       " 1352,\n",
       " 13,\n",
       " 191,\n",
       " 79,\n",
       " 638,\n",
       " 89,\n",
       " 2,\n",
       " 14,\n",
       " 9,\n",
       " 8,\n",
       " 106,\n",
       " 607,\n",
       " 624,\n",
       " 35,\n",
       " 534,\n",
       " 6,\n",
       " 227,\n",
       " 7,\n",
       " 129,\n",
       " 113]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "cell_type": "code",
   "source": "train_labels[0:20]  #二分类",
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.492910Z",
     "start_time": "2025-02-26T15:31:01.484463Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1],\n",
       "      dtype=int64)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 8
  },
  {
   "cell_type": "code",
   "source": [
    "print(\"train\", len(train_data), train_labels.shape)  #25000个样本，每个样本是一段话，每个单词用一个数字表示\n",
    "print(\"test\", len(test_data), test_labels.shape)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.501473Z",
     "start_time": "2025-02-26T15:31:01.492910Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train 25000 (25000,)\n",
      "test 25000 (25000,)\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.584483Z",
     "start_time": "2025-02-26T15:31:01.501473Z"
    }
   },
   "source": [
    "#载入词表，看下词表长度，词表就像英语字典\n",
    "word_index = imdb.get_word_index()\n",
    "print(len(word_index))\n",
    "print(type(word_index))\n",
    "#词表虽然有8万多，但是我们只载入了最高频的1万词！！！！"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "88584\n",
      "<class 'dict'>\n"
     ]
    }
   ],
   "execution_count": 10
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构造 word2idx 和 idx2word"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.636189Z",
     "start_time": "2025-02-26T15:31:01.584483Z"
    }
   },
   "source": [
    "word2idx = {word: idx + 3 for word, idx in word_index.items()}  # 0,1,2,3空出来做别的事,这里的idx是从1开始的,所以加3\n",
    "word2idx.update({\n",
    "    \"[PAD]\": 0,  # 填充 token\n",
    "    \"[BOS]\": 1,  # begin of sentence\n",
    "    \"[UNK]\": 2,  # 未知 token\n",
    "    \"[EOS]\": 3,  # end of sentence\n",
    "})\n",
    "#字典生成式\n",
    "idx2word = {idx: word for word, idx in word2idx.items()}  # 反向词典,id变为单词"
   ],
   "outputs": [],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "source": [
    "print(len(word2idx)) \n",
    "print(len(idx2word))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.644824Z",
     "start_time": "2025-02-26T15:31:01.636189Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "88588\n",
      "88588\n"
     ]
    }
   ],
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "source": [
    "idx2word[4825]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.661354Z",
     "start_time": "2025-02-26T15:31:01.644824Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'hello'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 13
  },
  {
   "cell_type": "code",
   "source": [
    "#想对句子长度画个直方图，看看长度分布\n",
    "length_list = [len(text) for text in train_data]\n",
    "plt.hist(length_list, bins=50)\n",
    "plt.xlabel(\"length\")\n",
    "plt.ylabel(\"frequency\")\n",
    "plt.axvline(500, label=\"max length\", c=\"gray\", ls=\":\")\n",
    "plt.legend()\n",
    "plt.show()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:01.992156Z",
     "start_time": "2025-02-26T15:31:01.661354Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "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wJr0tNts9erVdjNr2bKle4xGobp429KlS+25Puobx3nDKA1yEhMTZePGje4xwedwjnHOcbalHvQcwRuyJu3j135n3YL7+wF4n34o1i04k7HewPW11GMKw3HshUj9IU3PGfya8z20xUR99NFHFrzpOCJtFNCeD20hCu7KUho8/Pzzz1avLVu2pKtOR44ckbp169q5gzc9X6dOnc5Zd6eeFysjz302UTPKVCNZXaBPB2o5qxfrG06b0oJp8KP7nGOCgyFnv7PvXMdokKORtQ72Sk37hrVJElmf/iP7+9//7pYBICvT8Tw6vujhhx92XwtutXFo44I2GGjgpN1v2jCgPSRpUadOHes203G5BQsWvKB66mBvHc/7448/WnCltNXpzz//PCPwiZaUKFHTQqTdYzfffLOUKVMmKppZtcvO2XS0PbImberWvmndmHYPIKvTcUWrVq2ycbDaYvPkk0+mGIzsdKlpL4iOq9UxRjobTB9TtyKdTefOnW0ck84s00HVOhZXxw49+uijsnv37jSdQ3t0NAjT2W46YFwDIy1rI0Rwy5p2jenYIG28SB0sZbaouEPogC8dB6QDwBx6A9NfnrYaBdNZZrrPOSb1rDPn+fmO0ag3VOuQ0tlouj94AwAg0rTFWycXdejQwQYr64Dr4NYiHcyss63HjRsnZcuWtde0/Pvvv1vwlBb58uWTb775xoao6PfSliVtadIxROm5H7733nvWI9OsWTObWq8tVTouSAeOO3R8r06o0rpee+21EkkxgSgYWKEDoN98801riXG6NbRlRgddT5kyxabbO4O0NOrUyFcHxelAMR3ZrjPUtGlP6bQ+fTNo/6kGNjrAWqdXOgO9lPaBHjhwQGbPnp2m+mn3muZB0DpFc3CUlmn1O0a3ET/Rpljnd6/Nxxfazw8gOulNWlswdPJM8I0W0Wf37t0W+GgDSIsWLTLlPZCe+3fEB1XoICmdPdatW7cUYzz0B9CINC4uzpJC6Q+is4QaNWpkwZDS/AyahVin440ZM8aa3HT6ouYu0mBI9erVy0bZDx482PpUFyxYYNMTZ80iJ49fAiLNxaH0vUJABACZY8GCBTZAWz+MasOF3oe1i0xbjKJRxAMijRR16mCohFE6NV7HfWgLkc780tlh2vTn0JubJmzSRFYaKOXPn98Cq5EjR7rHaMSowY/mNNJkWprQSnMhMOXeH/T9o33uThkAkDmSk5MtaeS2bdusq0wHg2vSyGhNfxIVXWbRji4zAIhOdJkhKUxdZnxkBgBkeXy2969AmH73BEQAgCzL6X4JXq8M/nLi/9IJXOwY0YiPIQIyug9bl29xBthHa981gAujN0FN4Oss66BTxoPz3MDbTp8+bYvs6u/9YpPvEhDB802pmmLBKQPwHifvXEavdYXopBNmNGfSxQbCBETwNP3EoOv8OGUA3qM3Ql38U/PRaasw/CVXrlxhmUXMHQK++OQAwB/dZ+Qaw4ViUDUAAPA9Wojg+QF3P/30k5V1PR6SMwIAQuHuAE87efKkfPLJJ7ZpGQCAUGghgucHW5YvX94tAwAQCgERPE3zDnXv3j3S1QAARDm6zAAAgO8REAEAAN+jywyepkna3nnnHSv36NGDpTsAACEREMHTdLmOffv2uWUAAEIhIIKn6XId9913n1sGACAU7hDwNE3EWKlSpUhXAwAQ5RhUDQAAfI8WInh+6Y6tW7dauXLlyizdAQAIibsDPE2X65gyZYptLN0BADgbWojgabpcR5kyZdwyAAChEBDB0zTvUM+ePSNdDQBAlKPLDAAA+B4BEQAA8D26zOD5pTvef/99K3fp0oWlOwAAIREQwdN0uY5du3a5ZQAAQiEggqfpch0dOnRwywAAhMIdAp6miRirVq0a6WoAAKIcg6oBAIDv0UIEzy/dsXPnTiuXK1eOpTsAACFxd4Cn6XIdkyZNso2lOwAAZ0MLETxNl+soXry4WwYAIBQCInia5h16+OGHI10NAECUo8sMAAD4HgERAADwPbrM4PmlOz766CMrd+zYkaU7AAAhERDB03S5jm3btrllAABCISCCp+lyHe3atXPLAACEwh0CnqaJGGvVqhXpagAAolzEB1X/97//lfvuu0+KFi0qefPmlZo1a8qqVavc/drNMXz4cCldurTtb9mypWzZsiXFOQ4cOCCdO3eWggULSuHChaVHjx5y5MiRFMesW7dOmjZtKnny5JGyZcvKmDFjMu1nBAAA0S2iAdGff/4pjRs3toGuX331lWzatElefPFFufTSS91jNHD517/+JePHj5fly5dL/vz5JTY2VpKSktxjNBjauHGjzJ07V2bOnCnffPONPPTQQ+7+xMREadWqlZQvX15Wr14tzz//vDz99NPy1ltvZfrPjMxfukODbt20DABAKDGBCI40HTp0qCxZskS+/fbbkPu1amXKlJEBAwbIwIED7bVDhw5JyZIlZeLEiTZr6KeffpLq1avLypUrpV69enbM7Nmz5ZZbbpHdu3fb17/xxhvy+OOPy969eyVXrlzu954xY4Zs3rz5jO97/Phx24IDKm1V0u+trVDRqsLQWec9ZsfoNuInJ06ckFGjRll52LBh7u8fAOB9iYmJUqhQoTTdvyPaQvT5559bEHP33XdLiRIl5Nprr5V///vf7v7t27dbEKPdZA79wRo0aCBLly615/qo3WROMKT0eB07oi1KzjHNmjVLcTPUVqb4+HhrpUpNb6D6fZxNgyFkTbpch/N7ZOkOAEBUBkQ6HVpbb6688kqZM2eO9O7dWx599FFbiFNpMKS0RSiYPnf26aMGU8F0NlGRIkVSHBPqHMHfI5i2JGg06Wy7du0K68+NzKPdsf369bONHEQAgKicZaZjOrRl55///Kc91xaiDRs22Hihbt26RaxeuXPntg0AAPhDRFuIdOaYjv8JVq1aNdm5c6eVS5UqZY/79u1LcYw+d/bpY0JCQor9J0+etJlnwceEOkfw9wAAAP4V0YBIZ5jpOJ5gP//8s80GUxUrVrSAZf78+SkGSOnYoEaNGtlzfTx48KDNHnMsWLDAWp90rJFzjM4802UcHDojrUqVKilmtMF7NDjWpTt00zIAAFEXEPXv31+WLVtmXWZbt26VDz/80KbC9+nTx/brIFgd+/Hss8/aAOz169dL165dbeZY27Zt3Ral1q1bS8+ePWXFihU2a61v3742A02PU506dbIB1ZqfSKfnf/zxxzJ27FiJi4uL5I+PTKCBsQbdujHtHgAQlWOI6tevL9OnT7dBzCNHjrQWoVdeecXyCjkGDx4sf/31l+UV0pagJk2a2LR6TbDomDx5sgVBLVq0sNll7du3t9xFDp1h9PXXX1ugVbduXSlWrJglewzOVQRvyp49u9x6661uGQCAqMtD5MU8BpFEHiIAALJgHiIAAIBowOKu8DRtAN2/f7+VixcvTnJGAEBItBDB03RmoSb/1C14liEAAMFoIYLn5cuXL9JVAABEOQIieJqmWxg0aFCkqwEAiHJ0mQEAAN8jIAIAAL5Hlxk8TZfr0Czn6vbbb5ccOXjLAwDORAsRPE2X69AlX3Rj6Q4AwNnwcRmepst1xMbGumUAAEIhIIKnaRDUsGHDSFcDABDl6DIDAAC+RwsRPL90hy7qp3SBP5buAACEQgsRPE2X6xg7dqxtLN0BADgbWojgeTlz5ox0FQAAUY6ACJ5fuuMf//hHpKsBAIhydJkBAADfIyACAAC+R5cZPL90x5dffmnlW265haU7AAAh0UIET9PlOn788UfbWLoDAHA2fFyG5zNVN2/e3C0DABAKARE8TYOgZs2aRboaAIAoR5cZAADwPVqI4PmlO44ePWrlfPnysXQHACAkWojgabpcxwsvvGAbS3cAAM6GgAgAAPgeXWbw/NIdTz31VKSrAQCIcrQQAQAA3yMgAgAAvkeXGTy/dMe8efOs3LJlS5buAACERAsRPE2X61i+fLltLN0BADgbPi7D85mqmzRp4pYBAAiFgAiepkFQixYtIl0NAECUo8sMAAD4Hi1E8PzSHU6G6pw5c7J0BwAgJFqI4GkaDI0aNco2lu4AAJwNAREAAPA9uszgadpNNmzYMLcMAEDUtRA9/fTTNqYjeKtataq7PykpSfr06SNFixaVAgUKSPv27WXfvn0pzrFz505p06aN5MuXT0qUKCGDBg2yZHzBFi1aJHXq1JHcuXNL5cqVZeLEiZn2MyKy9D2l65npxvghAEDUdpldffXVsmfPHnf77rvv3H39+/eXL774QqZNmyaLFy+W3377Te688053/6lTpywYOnHihHz//fcyadIkC3aGDx/uHrN9+3Y7pnnz5rJmzRrp16+fPPjggzJnzpxM/1kBAEB0iniXmS6lUKpUqTNeP3TokLzzzjvy4Ycfyk033WSvTZgwQapVqybLli2Thg0bytdffy2bNm2ypRlKliwptWvXlmeeeUaGDBlirU/aKjB+/HipWLGivPjii3YO/XoNul5++WWJjY3N9J8XmUuDZm0hVDfeeCPJGQEA0dlCtGXLFilTpoxcccUV0rlzZ+sCU6tXr7ZZQbr+lEO708qVKydLly615/pYs2ZNC4YcGuQkJibKxo0b3WOCz+Ec45wjlOPHj9s5gjdk3YBIA2DdtAwAQNQFRA0aNLAurtmzZ8sbb7xh3VtNmzaVw4cPy969e62Fp3Dhwim+RoMf3af0MTgYcvY7+851jAY5x44dC1kvnaJdqFAhdytbtmxYf25knmzZstn7TDctAwAQdV1mN998s1uuVauW3bTKly8vU6dOlbx580as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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 14
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "source": [
    "length_list[0:10]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:02.003617Z",
     "start_time": "2025-02-26T15:31:01.994782Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[218, 189, 141, 550, 147, 43, 123, 562, 233, 130]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 15
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tokenizer"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:02.027932Z",
     "start_time": "2025-02-26T15:31:02.003617Z"
    }
   },
   "source": [
    "class Tokenizer:\n",
    "    def __init__(self, word2idx, idx2word, max_length=500, pad_idx=0, bos_idx=1, eos_idx=3, unk_idx=2):\n",
    "        self.word2idx = word2idx  #词表,单词到id\n",
    "        self.idx2word = idx2word  #词表，id到单词\n",
    "        self.max_length = max_length\n",
    "        self.pad_idx = pad_idx  #填充\n",
    "        self.bos_idx = bos_idx  #开始\n",
    "        self.eos_idx = eos_idx  #结束\n",
    "        self.unk_idx = unk_idx  #未知，未出现在最高频词表中的词\n",
    "\n",
    "    def encode(self, text_list):\n",
    "        \"\"\"\n",
    "        将文本列表转化为索引列表\n",
    "        :param text_list:当前批次的文本列表\n",
    "        :return:\n",
    "        \"\"\"\n",
    "        max_length = min(self.max_length, 2 + max(\n",
    "            [len(text) for text in text_list]))  #最大长度，最大长度是500，但是如果句子长度小于500，就取句子长度（句子长度是本组句子中最长的），2是为了留出开始和结束的位置\n",
    "        indices = []\n",
    "        for text in text_list:\n",
    "            index = [self.word2idx.get(word, self.unk_idx) for word in text]  #单词转化为id，未知的词用unk_idx代替\n",
    "            if len(index) < max_length:\n",
    "                index = index + [self.pad_idx] * (max_length - len(index))  #填充0\n",
    "            else:\n",
    "                index = index[:max_length]  #如果句子长度大于500，就截断\n",
    "            index = [self.bos_idx] + index + [self.eos_idx]  #添加开始和结束  \n",
    "            indices.append(index)\n",
    "        return torch.tensor(indices)  #二维列表转化为tensor\n",
    "\n",
    "    def decode(self, indices_list, remove_bos=True, remove_eos=True, remove_pad=True, split=False):\n",
    "        \"\"\"\n",
    "        将索引列表转化为文本列表\n",
    "        :param indices_list:某批次的索引列表\n",
    "        :param remove_bos:\n",
    "        :param remove_eos:\n",
    "        :param remove_pad:\n",
    "        :param split:\n",
    "        :return:\n",
    "        \"\"\"\n",
    "        text_list = []\n",
    "        for indices in indices_list:\n",
    "            text = []\n",
    "            for index in indices:\n",
    "                word = self.idx2word.get(index, \"[UNK]\")\n",
    "                if remove_bos and word == \"[BOS]\":\n",
    "                    continue\n",
    "                if remove_eos and word == \"[EOS]\":\n",
    "                    break\n",
    "                if remove_pad and word == \"[PAD]\":\n",
    "                    break\n",
    "                text.append(word)\n",
    "            text_list.append(\" \".join(text) if not split else text)\n",
    "        return text_list\n",
    "    \n",
    "tokenizer = Tokenizer(word2idx=word2idx, idx2word=idx2word)\n",
    "\n",
    "\n",
    "\n",
    "raw_text = [\"hello world\".split(), \"tokenize text datas with batch\".split(), \"this is a test\".split()]\n",
    "indices = tokenizer.encode(raw_text)  #encode支持批量处理\n",
    "decode_text = tokenizer.decode(indices.tolist(), remove_bos=False, remove_eos=False, remove_pad=False)\n",
    "print(\"raw text\")\n",
    "for raw in raw_text:\n",
    "    print(raw)\n",
    "print(\"indices\")\n",
    "for index in indices:\n",
    "    print(index)\n",
    "print(\"decode text\")\n",
    "for decode in decode_text:\n",
    "    print(decode)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "raw text\n",
      "['hello', 'world']\n",
      "['tokenize', 'text', 'datas', 'with', 'batch']\n",
      "['this', 'is', 'a', 'test']\n",
      "indices\n",
      "tensor([   1, 4825,  182,    0,    0,    0,    0,    0,    3])\n",
      "tensor([    1,     2,  3004,     2,    19, 19233,     0,     0,     3])\n",
      "tensor([   1,   14,    9,    6, 2181,    0,    0,    0,    3])\n",
      "decode text\n",
      "[BOS] hello world [PAD] [PAD] [PAD] [PAD] [PAD] [EOS]\n",
      "[BOS] [UNK] text [UNK] with batch [PAD] [PAD] [EOS]\n",
      "[BOS] this is a test [PAD] [PAD] [PAD] [EOS]\n"
     ]
    }
   ],
   "execution_count": 16
  },
  {
   "cell_type": "code",
   "source": [
    "train_data[0:1]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:02.039842Z",
     "start_time": "2025-02-26T15:31:02.027932Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([list([1, 14, 22, 16, 43, 530, 973, 1622, 1385, 65, 458, 4468, 66, 3941, 4, 173, 36, 256, 5, 25, 100, 43, 838, 112, 50, 670, 2, 9, 35, 480, 284, 5, 150, 4, 172, 112, 167, 2, 336, 385, 39, 4, 172, 4536, 1111, 17, 546, 38, 13, 447, 4, 192, 50, 16, 6, 147, 2025, 19, 14, 22, 4, 1920, 4613, 469, 4, 22, 71, 87, 12, 16, 43, 530, 38, 76, 15, 13, 1247, 4, 22, 17, 515, 17, 12, 16, 626, 18, 2, 5, 62, 386, 12, 8, 316, 8, 106, 5, 4, 2223, 5244, 16, 480, 66, 3785, 33, 4, 130, 12, 16, 38, 619, 5, 25, 124, 51, 36, 135, 48, 25, 1415, 33, 6, 22, 12, 215, 28, 77, 52, 5, 14, 407, 16, 82, 2, 8, 4, 107, 117, 5952, 15, 256, 4, 2, 7, 3766, 5, 723, 36, 71, 43, 530, 476, 26, 400, 317, 46, 7, 4, 2, 1029, 13, 104, 88, 4, 381, 15, 297, 98, 32, 2071, 56, 26, 141, 6, 194, 7486, 18, 4, 226, 22, 21, 134, 476, 26, 480, 5, 144, 30, 5535, 18, 51, 36, 28, 224, 92, 25, 104, 4, 226, 65, 16, 38, 1334, 88, 12, 16, 283, 5, 16, 4472, 113, 103, 32, 15, 16, 5345, 19, 178, 32])],\n",
       "      dtype=object)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 17
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:02.051783Z",
     "start_time": "2025-02-26T15:31:02.041864Z"
    }
   },
   "source": [
    "# 看看训练集的数据\n",
    "tokenizer.decode(train_data[:1], remove_bos=False, remove_eos=False, remove_pad=False)"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"[BOS] this film was just brilliant casting location scenery story direction everyone's really suited the part they played and you could just imagine being there robert [UNK] is an amazing actor and now the same being director [UNK] father came from the same scottish island as myself so i loved the fact there was a real connection with this film the witty remarks throughout the film were great it was just brilliant so much that i bought the film as soon as it was released for [UNK] and would recommend it to everyone to watch and the fly fishing was amazing really cried at the end it was so sad and you know what they say if you cry at a film it must have been good and this definitely was also [UNK] to the two little boy's that played the [UNK] of norman and paul they were just brilliant children are often left out of the [UNK] list i think because the stars that play them all grown up are such a big profile for the whole film but these children are amazing and should be praised for what they have done don't you think the whole story was so lovely because it was true and was someone's life after all that was shared with us all\"]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 18
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据集与 DataLoader"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:04.429307Z",
     "start_time": "2025-02-26T15:31:02.051783Z"
    }
   },
   "source": [
    "from torch.utils.data import Dataset, DataLoader\n",
    "\n",
    "\n",
    "class IMDBDataset(Dataset):\n",
    "    def __init__(self, data, labels, remain_length=True):\n",
    "        if remain_length:  #字符串输出样本中，是否含有【BOS】和【EOS】，【PAD】\n",
    "            self.data = tokenizer.decode(data, remove_bos=False, remove_eos=False, remove_pad=False)\n",
    "        else:\n",
    "            # 缩减一下数据\n",
    "            self.data = tokenizer.decode(data)\n",
    "        self.labels = labels\n",
    "\n",
    "    def __getitem__(self, index):\n",
    "        text = self.data[index]\n",
    "        label = self.labels[index]\n",
    "        return text, label\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.data)\n",
    "\n",
    "\n",
    "def collate_fct(batch):\n",
    "    \"\"\"\n",
    "    将batch数据处理成tensor形式\n",
    "    :param batch:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    text_list = [item[0].split() for item in batch]  #batch是128样本，每个样本类型是元组，第一个元素是文本，第二个元素是标签\n",
    "    label_list = [item[1] for item in batch]\n",
    "    text_list = tokenizer.encode(text_list).to(dtype=torch.int)  # 文本转化为索引\n",
    "    return text_list, torch.tensor(label_list).reshape(-1, 1).to(dtype=torch.float)\n",
    "\n",
    "\n",
    "train_ds = IMDBDataset(train_data, train_labels)\n",
    "test_ds = IMDBDataset(test_data, test_labels)"
   ],
   "outputs": [],
   "execution_count": 19
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:04.438670Z",
     "start_time": "2025-02-26T15:31:04.429307Z"
    }
   },
   "cell_type": "code",
   "source": [
    "print(train_ds[0][0])\n",
    "print(train_ds[0][1])"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[BOS] this film was just brilliant casting location scenery story direction everyone's really suited the part they played and you could just imagine being there robert [UNK] is an amazing actor and now the same being director [UNK] father came from the same scottish island as myself so i loved the fact there was a real connection with this film the witty remarks throughout the film were great it was just brilliant so much that i bought the film as soon as it was released for [UNK] and would recommend it to everyone to watch and the fly fishing was amazing really cried at the end it was so sad and you know what they say if you cry at a film it must have been good and this definitely was also [UNK] to the two little boy's that played the [UNK] of norman and paul they were just brilliant children are often left out of the [UNK] list i think because the stars that play them all grown up are such a big profile for the whole film but these children are amazing and should be praised for what they have done don't you think the whole story was so lovely because it was true and was someone's life after all that was shared with us all\n",
      "1\n"
     ]
    }
   ],
   "execution_count": 20
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:04.447353Z",
     "start_time": "2025-02-26T15:31:04.438670Z"
    }
   },
   "source": [
    "batch_size = 128\n",
    "train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True, collate_fn=collate_fct)  #collate_fn是处理batch的函数\n",
    "test_dl = DataLoader(test_ds, batch_size=batch_size, shuffle=False, collate_fn=collate_fct)"
   ],
   "outputs": [],
   "execution_count": 21
  },
  {
   "cell_type": "code",
   "source": [
    "#要看到每个batch的长度不同，需要修改batch_size为12\n",
    "i=0\n",
    "for text, label in train_dl:\n",
    "    print(text.shape, label.shape)\n",
    "    i+=1\n",
    "    if i==50:\n",
    "        break"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:05.639540Z",
     "start_time": "2025-02-26T15:31:04.447353Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n",
      "torch.Size([128, 502]) torch.Size([128, 1])\n"
     ]
    }
   ],
   "execution_count": 22
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": "## 定义模型"
  },
  {
   "cell_type": "code",
   "source": [
    "# target output size of 5\n",
    "m = nn.AdaptiveAvgPool1d(1)  # 自适应平均池化\n",
    "input = torch.randn(1, 3, 6)\n",
    "output = m(input)\n",
    "output.size()  #可以看到最后一维变成了1"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:05.685901Z",
     "start_time": "2025-02-26T15:31:05.639540Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 3, 1])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 23
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:05.703143Z",
     "start_time": "2025-02-26T15:31:05.687904Z"
    }
   },
   "source": [
    "class AddingModel(nn.Module):\n",
    "    def __init__(self, embedding_dim=16, hidden_dim=64, vocab_size=vocab_size):\n",
    "        super(AddingModel, self).__init__()\n",
    "        self.embeding = nn.Embedding(vocab_size, embedding_dim)  # 词嵌入\n",
    "        self.pool = nn.AdaptiveAvgPool1d(1)  # 自适应平均池化,对应tf是全局平均值池化\n",
    "        self.layer = nn.Linear(embedding_dim, hidden_dim)  # 全连接层\n",
    "        self.fc = nn.Linear(hidden_dim, 1)  # 全连接层\n",
    "\n",
    "    def forward(self, x):\n",
    "        # [bs, seq length] [128, 500]  [128,500,10000]--->[128,500,16]\n",
    "        x = self.embeding(x)\n",
    "        # [bs, seq length, embedding_dim]-->[bs, embedding_dim, seq length]，尺寸[128,500,16]--》[128,16,500]\n",
    "        x = x.permute(0, 2, 1)\n",
    "        x = self.pool(x)  # 每个样本变为一个密集向量，在seq_length维度上进行平均池化，[128,16,500]-->[128,16,1]\n",
    "        x=x.squeeze(2)  # [bs, embedding_dim, 1] ->[bs, embedding_dim]\n",
    "        # [bs, embedding_dim] -> [bs, hidden_dim]\n",
    "        x = self.layer(x)\n",
    "        x = self.fc(x)  # [bs, hidden_dim] -> [bs, 1]\n",
    "\n",
    "        return x\n",
    "\n",
    "\n",
    "for key, value in AddingModel().named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "            embeding.weight             paramerters num: 160000\n",
      "              layer.weight              paramerters num: 1024\n",
      "               layer.bias               paramerters num: 64\n",
      "               fc.weight                paramerters num: 64\n",
      "                fc.bias                 paramerters num: 1\n"
     ]
    }
   ],
   "execution_count": 24
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:05.855454Z",
     "start_time": "2025-02-26T15:31:05.705145Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)  # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        # 二分类\n",
    "        preds = logits > 0\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "\n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 25
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:06.083909Z",
     "start_time": "2025-02-26T15:31:05.855454Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "\n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\",\n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "        )\n",
    "\n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "\n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "\n",
    "        )\n",
    "\n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 26
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:06.093781Z",
     "start_time": "2025-02-26T15:31:06.083909Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "\n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "\n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "\n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 27
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:31:06.100913Z",
     "start_time": "2025-02-26T15:31:06.093781Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "\n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else:\n",
    "            self.counter += 1\n",
    "\n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 28
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:35:42.273281Z",
     "start_time": "2025-02-26T15:31:06.100913Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "        model,\n",
    "        train_loader,\n",
    "        val_loader,\n",
    "        epoch,\n",
    "        loss_fct,\n",
    "        optimizer,\n",
    "        tensorboard_callback=None,\n",
    "        save_ckpt_callback=None,\n",
    "        early_stop_callback=None,\n",
    "        eval_step=500,\n",
    "):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "\n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits > 0 #当sigmoid输出大于0.5时，预测为1，否则预测为0，这里大于0，刚好sigmoid的值是0.5，预测为1\n",
    "\n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())\n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "\n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "\n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "\n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step,\n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                        )\n",
    "\n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "\n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "\n",
    "    return record_dict\n",
    "\n",
    "\n",
    "epoch = 20\n",
    "\n",
    "model = AddingModel()\n",
    "\n",
    "# 1. 定义损失函数 采用二进制交叉熵损失, 先sigmoid再计算交叉熵\n",
    "loss_fct = F.binary_cross_entropy_with_logits\n",
    "# loss_fct =nn.BCEWithLogitsLoss()\n",
    "# 2. 定义优化器 采用 adam\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(\"runs/imdb-adding\")\n",
    "# tensorboard_callback.draw_model(model, [1, MAX_LENGTH])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(\"checkpoints/imdb-adding\", save_step=len(train_dl), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=5)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model,\n",
    "    train_dl,\n",
    "    test_dl,\n",
    "    epoch,\n",
    "    loss_fct,\n",
    "    optimizer,\n",
    "    tensorboard_callback=tensorboard_callback,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_dl)\n",
    ")"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/3920 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "b250ccc5f41b4c288acbc5b1ae3c8343"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 16 / global_step 3136\n"
     ]
    }
   ],
   "execution_count": 29
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:35:42.752458Z",
     "start_time": "2025-02-26T15:35:42.275293Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):\n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        # axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        # axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "plot_learning_curves(record, sample_step=10)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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acuXL9dyc3O1uXPntvq282s98MAD2tKlS9m9T1u2bJnu/48++qiWlZWlvfHGG9rWrVu1K664Quvdu7dWVVUVWObyyy/XiouLtY8//lh7//33tb59+2rTp08P/P/06dNaXl6eduONN2pffPGF9te//lVLSUnRnn322TYdy0033SS2Vd1PJ06c0C3jhrFMnjxZe+GFF8T6t2zZok2dOlXr1auXVl5eHtFjau/evVpqaqp29913a19++aX21FNPaXFxcdqKFSsiNhan47n44ovF51vdN/xeu208//jHP7S33npL++qrr7Rdu3Zp999/v5aQkCDG1tH2C4juc1NHPi8xODfh3NSa34E4L53vunFYEdVCZ/To0dodd9wRuN/Q0KD16NFDW7hwoeYm+ITCX0BmnDp1Shxwr732WuCxHTt2iC+79evXi/t8UHm9Xq2kpCSwzNNPP61lZmZqNTU1Wlth/AJubGzUunXrpv3nf/6nbjxJSUniS5ThA56f98knnwSWefvttzWPx6MdOnRI3P/Tn/6kZWdn68YyZ84crX///m02FnkyufLKKy2f49axHD16VGzXu+++G9Fj6te//rWYCKlcf/314gTQmhjHI08od911l+Vz3DwePh6ef/75Dr9fQHSdm6LlvMTg3OTOsUTTuQnnJa8rx8FEbepabW0tbdq0SYSjJV6vV9xfv349uQ0OmXNYuk+fPiK8zGFAhsdQV1enGwenD/Tq1SswDv49ePBgysvLCywzefJkKisro+3bt1N7sW/fPiopKdFte1ZWlkjTULedw+gjR44MLMPL877asGFDYJlx48ZRYmKibnwcJj558mSbjolDrxyW7d+/P82aNYuOHz8e+J9bx3L69GnxOycnJ6LHFC+jrkMu09qfL+N4JC+//DLl5ubSoEGDaO7cuVRZWRn4nxvH09DQQK+88gpVVFSIVIGOvl9A9J2bovG8xODc5I6xRNO5Ceelwa4ah0o8RSmlpaVih6lvPMP3d+7cSW6Cv1w5V5G/oA4fPkwLFiwQebJffPGF+DLmLx7+kjKOg//H8G+zccr/tRfytc22Td12/nJWiY+PF18W6jK9e/cOWof8X3Z2NrUFnPM8bdo0sS179uyh+++/n6ZMmSI+qHFxca4cS2NjI/3iF7+gCy64QHzRyteJxDFltQx/uVVVVYm890hjNh7mhhtuoMLC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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 30
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-26T15:35:49.096660Z",
     "start_time": "2025-02-26T15:35:42.752458Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(\"checkpoints/imdb-adding/best.ckpt\", map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_dl, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3075\n",
      "accuracy: 0.8786\n"
     ]
    }
   ],
   "execution_count": 31
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
